package com.demo.filter;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 请求包装过滤器
 * 功能：
 * - 跳过大文件和二进制流
 * - 安全异常处理
 */
@Component
public class RequestWrapperFilter extends OncePerRequestFilter {
    private static final String[] EXCLUDE_CONTENT_TYPES = {
        "multipart/form-data", 
        "application/octet-stream"
    };

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                   HttpServletResponse response,
                                   FilterChain chain) 
        throws ServletException, IOException {
        // 跳过不需要包装的请求类型
        if (shouldSkipWrapper(request)) {
            chain.doFilter(request, response);
            return;
        }

        try {
            // 包装请求并继续处理
            BodyReaderHttpServletRequestWrapper wrappedRequest = 
                new BodyReaderHttpServletRequestWrapper(request);
            chain.doFilter(wrappedRequest, response);
        } catch (IOException ex) {
            handleIOException(ex, response);
        }
    }

    /**
     * 判断是否需要跳过包装
     */
    private boolean shouldSkipWrapper(HttpServletRequest request) {
        String contentType = request.getContentType();
        if (contentType == null) return false;
        
        for (String type : EXCLUDE_CONTENT_TYPES) {
            if (contentType.startsWith(type)) return true;
        }
        return false;
    }

    /**
     * 统一处理IO异常
     */
    private void handleIOException(IOException ex, HttpServletResponse response) 
        throws IOException {
        if (ex.getMessage().contains("exceeds maximum allowed size")) {
            response.sendError(413, "Request body too large");
        } else {
            response.sendError(500, "Internal server error");
        }
    }
}
